package com.dragon.english_practice_back.filter;

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.dragon.english_practice_back.enums.RedisPrefixEnum;
import com.dragon.english_practice_back.service.AuthenticationUtil;
import com.dragon.english_practice_back.util.JWTUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Slf4j
@Component
public class TokenFilter extends OncePerRequestFilter {

    StringRedisTemplate stringRedisTemplate;
    AuthenticationUtil authenticationUtil;

    public TokenFilter(AuthenticationUtil authenticationUtil, StringRedisTemplate stringRedisTemplate){

        this.stringRedisTemplate = stringRedisTemplate;
        this.authenticationUtil = authenticationUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        // 去除token头的Bearer
        if (StrUtil.isNotBlank(token)){
            token = token.replace("Bearer ", "");
        }

        //token不存在
        if (StrUtil.isAllEmpty(token)){
            log.info("not carry token");
            filterChain.doFilter(request, response);
            return;
        }

        //解析token
        int id = 0;
        try{
            DecodedJWT decodedJWT = JWTUtil.getToken(token);
            Claim claimId = decodedJWT.getClaim("id");
            id = Integer.parseInt(claimId.asString());
        }
        catch(JWTDecodeException e){
            log.error("token decode exception message:{} origin token: {}", e.getMessage(), token);
            filterChain.doFilter(request, response);
            return;
        }

        //获取redis里的token
        String rToken = stringRedisTemplate.opsForValue().get(RedisPrefixEnum.ACCESS_TOKEN.getPrefix() + id);

        //如果前端传的token与redis里的token不匹配
        if (StrUtil.isAllEmpty(rToken) || !rToken.equals(token)) {
            log.error("token no match");
            filterChain.doFilter(request, response);
            return;
        }

        //加载用户信息
        authenticationUtil.loadUserData(id);

        filterChain.doFilter(request, response);
    }
}
